/******************************************************************************
 * Product: Adempiere ERP & CRM Smart Business Solution                        *
 * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved.                *
 * This program is free software; you can redistribute it and/or modify it    *
 * under the terms version 2 of the GNU General Public License as published   *
 * by the Free Software Foundation. This program is distributed in the hope   *
 * that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.           *
 * See the GNU General Public License for more details.                       *
 * You should have received a copy of the GNU General Public License along    *
 * with this program; if not, write to the Free Software Foundation, Inc.,    *
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.                     *
 * For the text or an alternative of this public license, you may reach us    *
 * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA        *
 * or via info@compiere.org or http://www.compiere.org/license.html           *
 *****************************************************************************/
package org.adempiere.apps.form;

import java.awt.*;
import java.beans.PropertyChangeEvent;
import java.sql.*;
import java.util.*;
import java.util.logging.*;

import javax.swing.table.*;
import org.adempiere.model.MBarcodeTrxLine;
import org.compiere.apps.*;
import org.compiere.apps.form.FormFrame;
import org.compiere.grid.ed.*;
import org.compiere.model.*;
import org.compiere.util.*;
import org.jboss.util.Strings;
/**
 *  Barcode Transaction Form Out
 *
 *  @author  Shindu
 *  @version 1.1
 *  @since May 2013
 */


public class BarcodeTransactionOut extends BarcodeTransaction
{
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 121224L;

	/**
	 *	Initialize Panel
	 *  @param WindowNo window
	 *  @param frame frame
	 */
	public void init (int WindowNo, FormFrame frame)
	{
		//
		Env.setContext(Env.getCtx(), WindowNo, "IsSOTrx", "Y");
		isSOTrx=true;
		super.init(WindowNo, frame);
	}	//	init
    
	/**
	 * Set Lookup
	 * @throws Exception
	 */
	protected void initLookup () throws Exception
	{
		super.initLookup();
		MLookup lookup;
		int AD_Column_ID=3809;
		lookup = MLookupFactory.get (Env.getCtx(), p_WindowNo, 0, AD_Column_ID, DisplayType.Search);
		cOrderField = new VLookup ("C_Order_ID", true, false, true, lookup);				
	}   
	
	
	/**
	 *  Static Init
	 *  @throws Exception
	 */
	protected void jbInit() throws Exception {
		super.jbInit();

		// Order
		parameterStdPanel.add(cOrderLabel, new GridBagConstraints(0, 1, 1, 1,
				0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE,
				new Insets(5, 5, 5, 5), 0, 0));
		parameterStdPanel.add(cOrderField, new GridBagConstraints(1, 1, 1, 1,
				0.0, 0.0, GridBagConstraints.WEST,
				GridBagConstraints.HORIZONTAL, new Insets(5, 0, 5, 5), 0, 0));

		// Doc type
		parameterStdPanel.add(docTypeLabel, new GridBagConstraints(0, 2, 1, 1,
				0.0, 0.0, GridBagConstraints.EAST, GridBagConstraints.NONE,
				new Insets(5, 5, 5, 5), 0, 0));
		parameterStdPanel.add(docTypeField, new GridBagConstraints(1, 2, 1, 1,
				0.0, 0.0, GridBagConstraints.WEST,
				GridBagConstraints.HORIZONTAL, new Insets(5, 0, 5, 5), 0, 0));
		// Eceran
		parameterStdPanel.add(isEceran, new GridBagConstraints(2, 2, 1, 1, 0.0,
				0.0, GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL,
				new Insets(5, 0, 5, 5), 0, 0));

		parameterStdPanel.remove(poReference);
		parameterStdPanel.remove(poReferenceField);
		//
		bPartnerField.addVetoableChangeListener(this);
		cOrderField.addVetoableChangeListener(this);
	} // jbInit

	/**
	 *  Dynamic Init (prepare dynamic fields)
	 *  @throws Exception if Lookups cannot be initialized
	 */
	protected void dynInit() throws Exception
	{
		super.dynInit();
		cOrderLabel.setText(Msg.translate(Env.getCtx(), "C_Order_ID"));
		cOrderField.setMandatory(true);
		isEceran.setSelected(false);
		poReference.setVisible(false);
		poReferenceField.setVisible(false);
	}   //  dynInit

	/**
	 *  Vetoable Change Listener.
	 *  - Business Partner
	 *  - Order 
	 *  @param e event
	 */
	public void vetoableChange (PropertyChangeEvent e)
	{
		String name = e.getPropertyName();
		Object value = e.getNewValue();
		log.config(name + "=" + value);
		if (value == null)
			return;
		if (name.equals("C_BPartner_ID")){
			Env.setContext(Env.getCtx(), p_WindowNo, "C_BPartner_ID", (Integer) value);
			cOrderField.setValue(null);
			data.clear();
			loadTableOIS(data);
		}else if(name.equals("C_Order_ID")){
			loadOrderLines((Integer) value);
		}
	}   //  vetoableChange
	
	/**
	 * Reset
	 */
	protected void resetValue(){
		super.resetValue();
		cOrderField.setValue(null);
	}
	
	/**
	 * Check input.
	 * @return
	 */
	protected String checkInput(){
		String errMsg=super.checkInput();
		if (cOrderField.getValue()==null && errMsg.equals(Strings.EMPTY)){			
			cOrderField.requestFocus();
			errMsg="Sales order is mandatory!";
		}
		return errMsg;
	}
		
		
	/**
	 * Pengecekan tambahan.
	 * Cek line order
	 * @return
	 */
	protected String barcodeValidation(String[] barcode) {
		// Get data via vector find
		// int idxdata = dataPN.indexOf(barcode[0]);
		// Get data manual
		selectedIndex = findIndex(barcode);
		if (selectedIndex <0)
			return "Product not found on this Sales Order";
		Vector<Object> line = data.get(selectedIndex);
		if (line == null)
			return "Product not found on this Sales Order";
		return Strings.EMPTY;
	}

	/**
	 * Enable/Disable header control
	 * @param enabled
	 */
	protected void enableHeader(boolean enabled){
		super.enableHeader(enabled);
		cOrderField.setReadWrite(enabled);
		
	}
	
	
	private void loadOrderLines(int C_Order_ID)
	{
		if (locatorField.getValue()!=null){
			MOrder ord = new MOrder(Env.getCtx(), C_Order_ID, null);			
			MLocator loc = new MLocator(Env.getCtx(), (Integer) locatorField.getValue(), null);
			if (ord.getM_Warehouse_ID()!=loc.getM_Warehouse_ID()){
				ADialog.beep();
				ADialog.warn(p_WindowNo, null, "","Order warehouse not same to selected locator's warehouse ");
				return;
			}
		}
				
		String sql=	"SELECT ordl.c_orderline_id, ordl.m_product_id, prd.name, prd.upc, " +
						"ordl.c_uom_id, uom.uomsymbol, ordl.qtyordered, ordl.qtyreserved, ordl.qtydelivered " +
				"FROM c_orderline ordl " +
				"INNER JOIN m_product prd on ordl.m_product_id=prd.m_product_id " +
				"INNER JOIN c_uom uom on ordl.c_uom_id=uom.c_uom_id " +
				"WHERE ordl.c_order_id=? AND ordl.qtyreserved<>0 " +
				"ORDER BY ordl.line ";
		try {
			PreparedStatement pstmt = DB.prepareStatement(sql, null);
			pstmt.setInt(1, C_Order_ID);
			ResultSet rs = pstmt.executeQuery();
			statusBar.setStatusLine("Loading...");
			data.clear();		
			while (rs.next()){
				
				addData(rs.getString("upc"), 
						rs.getInt("m_product_id"),
						rs.getString("name"),
						rs.getInt("c_uom_id"),
						rs.getString("uomsymbol"),						 
						rs.getDouble("qtyreserved"), 
						0.0, 
						rs.getDouble("qtyreserved"),
						rs.getInt("c_orderline_id"));
				statusBar.invalidate();
			}
			loadTableOIS(data);
			statusBar.setStatusLine("Ready " + data.size() + " lines");
			rs.close();
			pstmt.close();			
		} catch (SQLException e) {
			log.log(Level.SEVERE, sql.toString(), e);			
		}
	}
	
	/**
	 * Find data index manual
	 * @param Bacode scan (Array of string) 
	 *        Index 0 = Barcode UPC
	 *        Index 1 = Quantity
	 * @return
	 */
	protected int findIndex(String[] barcode){
		//UPC=1
		//Remain=6
		int notfindresult=-1;
		Double tmp;
		for(int i=0;i<dataTable.getRowCount();i++){			
			//cek UPC (barcode[0])
			if (dataTable.getModel().getValueAt(i, 1).equals(barcode[0])){
				tmp = (Double) dataTable.getModel().getValueAt(i, 6);
				//Cek apakah sisa scan cukup, jika tidak find next
				//Hanya berlaku untuk colly. Tida bisa split 2 line jadi 1 scan
				if (tmp.compareTo(Double.valueOf(barcode[1]))>=0){ 
					return i;
				}
				notfindresult=i;
			}
		}
		return notfindresult;
	}
	/**
	 * Add data to vector as row
	 * @param PartNumber
	 * @param MProductID
	 * @param ProductName
	 * @param UomID
	 * @param UomCode
	 * @param qty, in unit uom/inventory uom
	 * @param scanned qty
	 * @param remain qty to scan
	 * @param OrderLineID
	 */
	private void addData(String PartNumber, int MProductID, String ProductName, int UomID, String UomCode,
			double qty, double scanned, double remain, int OrderLineID) {
		Vector<Object> line = new Vector<Object>(8);
		line.add(OrderLineID); // 0-Orderline
		line.add(PartNumber); // 1-PartNumber
		KeyNamePair pp = new KeyNamePair(MProductID, ProductName);
		line.add(pp); // 2-Product and Name
		line.add(qty); // 3-Qty
		pp = new KeyNamePair(UomID, UomCode);
		line.add(pp); // 4-UOM
		line.add(scanned); // 5-Scan qty
		line.add(remain); // 6-Remain	
		line.add(0);//7-scan count
		data.add(line);		
	    totalLines++;
	}
	
	/**
	 * UPdate data method 2. Direct update grid
	 * @param index to update
	 * @param scanned qty
	 */
	protected String updateLine(int index, double scanned) {
		TableModel tmpData= dataTable.getModel();
		double remain = (Double) tmpData.getValueAt(index, 6) -  scanned; //6-Remain
		if (remain<0){			
			return "Qty remain not sufficient for new barcode scan.";
		}
		scanned+= (Double) tmpData.getValueAt(index, 5); //5-Scan qty
		int count= (Integer) tmpData.getValueAt(index, 7); //5-Scan count
		//
		tmpData.setValueAt(scanned, index, 5); //scan qty
		tmpData.setValueAt(remain, index, 6); //remain
		tmpData.setValueAt(count+1, index, 7); //scan count
		try{
			dataTable.scrollRectToVisible(dataTable.getCellRect(index, 0, true));
		}catch(Exception ex){
			System.out.println(ex.getMessage());
		}		
	    dataTable.getSelectionModel().setSelectionInterval(index, index);
	    totalScan++;
	    return Strings.EMPTY;
	}
	
	/**
	 * Delete barcode transaction line 
	 */
	protected void deleteLine(){		
		/**delete lines **/
		if (M_BarcodeTrx_ID==0)
			return;	
		if ((Double) dataTable.getValueAt(dataTable.getSelectedRow(), 5)<=0){
			ADialog.warn(p_WindowNo, this,"", "Qty=0");
			return;
		}			
		int C_OrderLine_ID= (Integer) dataTable.getValueAt(dataTable.getSelectedRow(), 0); //get id
		Trx trx=Trx.get(Trx.createTrxName(),true);
		MBarcodeTrxLine line = MBarcodeTrxLine.getLastLine(Env.getCtx(), 
				M_BarcodeTrx_ID, C_OrderLine_ID, trx.getTrxName());
		if (line==null)
			return;
		double qty= line.getQty().doubleValue();
		double remain=0.0;
		int count;
		boolean isOK=line.delete(true);
		trx.commit();
		trx.close();
		if (isOK){
			DefaultTableModel tmpData= (DefaultTableModel) dataTable.getModel();
			//
			remain= qty + (Double) tmpData.getValueAt(dataTable.getSelectedRow(), 6);//remain
			qty= -qty + (Double) tmpData.getValueAt(dataTable.getSelectedRow(), 5) ;//scanned
			count = (Integer) tmpData.getValueAt(dataTable.getSelectedRow(), 7);//scan count
			//
			tmpData.setValueAt(qty, dataTable.getSelectedRow(), 5); //scan qty
			tmpData.setValueAt(remain, dataTable.getSelectedRow(), 6); //remain
			tmpData.setValueAt(count-1, dataTable.getSelectedRow(), 7); //scan count
			totalScan--;
		}else{
			ADialog.warn(p_WindowNo, this,"", "Error delete line.");
		}				
	}
		
	
	/**
	 * Load data to mini table
	 * @param data
	 */
	private void loadTableOIS(Vector<Vector<Object>> data) {
		//  Header Info
		    Vector<String> columnNames = new Vector<String>(8);
		    columnNames.add("id");
		    columnNames.add(Msg.translate(Env.getCtx(), "UPC"));
		    columnNames.add(Msg.translate(Env.getCtx(), "M_Product_ID"));		    
		    columnNames.add(Msg.translate(Env.getCtx(), "Quantity"));		    
		    columnNames.add("UOM");
		    columnNames.add("Scan Qty");
		    columnNames.add("Remain");
		    columnNames.add("Scan Count");
		    //  Set Model
		    DefaultTableModel model = new DefaultTableModel(data, columnNames);		   
		    dataTable.setModel(model);

		    //
		    dataTable.setColumnClass(0, Integer.class, true);        //  0-ID 
		    dataTable.setColumnVisibility(dataTable.getColumn("id"), false);//not visible
		    dataTable.setColumnClass(1, String.class, true);        //  1-UPC
		    dataTable.setColumnClass(2, String.class, true);        //  2-Product
		    dataTable.setColumnClass(3, Double.class, true);        //  3-Qty
		    dataTable.setColumnClass(4, String.class, true);        //  4-UOm
		    dataTable.setColumnClass(5, Double.class, true);        //  5-Scan Qty
		    dataTable.setColumnClass(6, Double.class, true);        //  6-Remain		    
		    dataTable.setColumnClass(7, Integer.class, true);        //  7-Scan count
		     
		    dataTable.autoSize();
		    
		    
		    
		    //dataTable.se
		}
	
}


